package com.ruicar.afs.cloud.workflow.greatwall.processor.impl.objcode;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.AfsFlowQueryRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.FlowExceptionRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.FlowExceptionResponse;
import com.ruicar.afs.cloud.workflow.api.enums.FlowStatus;
import com.ruicar.afs.cloud.workflow.api.util.FlowMappingHelper;
import com.ruicar.afs.cloud.workflow.greatwall.dto.GwtRequest;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowBizData;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowMappingInfo;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowNoticeException;
import com.ruicar.afs.cloud.workflow.greatwall.processor.GwfObjectCodeProcessor;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowBizDataService;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowMappingInfoService;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowNoticeExceptionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.text.MessageFormat;

import static com.ruicar.afs.cloud.workflow.api.constant.FlowConstant.FLOW_EXCEPTION_DESC_KEY;

@Slf4j
public abstract class AbsFlowErrorNoticeProcessor extends AbsGwfNoticeProcessor implements GwfObjectCodeProcessor {

    public AbsFlowErrorNoticeProcessor(AfsGreatWallWorkflowBizDataService afsGreatWallWorkflowBizDataService, AfsGreatWallWorkflowNoticeExceptionService afsGreatWallWorkflowNoticeExceptionService, AfsGreatWallWorkflowMappingInfoService afsGreatWallWorkflowMappingInfoService) {
        super(afsGreatWallWorkflowBizDataService, afsGreatWallWorkflowNoticeExceptionService);
        this.afsGreatWallWorkflowMappingInfoService = afsGreatWallWorkflowMappingInfoService;
    }

    /**
     * Afs great wall workflow mapping info service
     * <p>Description: </p>
     */
    private final AfsGreatWallWorkflowMappingInfoService afsGreatWallWorkflowMappingInfoService;
    /**
     * Process string
     *
     * @param request request
     * @return the string
     */
    @Override
    public String process(GwtRequest request) {
        log.info("任务分配失败通知{}", request);
        AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData = afsGreatWallWorkflowBizDataService.getBizDataObjServiceIdAndDataId(request.getServiceId(), request.getDataId());
        AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo = afsGreatWallWorkflowMappingInfoService.queryMappingByServiceId(request.getServiceId());
        FlowExceptionRequest flowExceptionRequest = getFlowExceptionRequest(request);
        flowExceptionRequest.setServiceId(request.getServiceId());
        flowExceptionRequest.setBizDataId(request.getDataId());
        flowExceptionRequest.setAfsFlowKey(FlowMappingHelper.getAfsKey(request.getServiceId()));
        if (afsGreatWallWorkflowBizDataService.exception(request.getServiceId(), request.getDataId())) {
            if (afsGreatWallWorkflowBizData != null) {
                saveException(request, afsGreatWallWorkflowBizData.getFlowInstanceId(), (genExceptionCheckCode(MessageFormat.format("{0}-{1}-{2}", request.getServiceId(), request.getDataId(), flowExceptionRequest.getExceptionId()))));
            }
            return bizError;
        }
        FlowExceptionResponse flowExceptionResponse = new FlowExceptionResponse();
        try {
            if (afsGreatWallWorkflowMappingInfo != null) {
                if(FlowMappingHelper.autoProcess(request.getServiceId()).contains(AfsEnumUtil.key(objectCode()))){
                    log.info("{}配置为自动处理，不通知业务端",FlowMappingHelper.getAfsKey(request.getServiceId()));
                    saveError(request,afsGreatWallWorkflowBizData,true);
                    String exceptionCheckCode =  (genExceptionCheckCode(MessageFormat.format("{0}-{1}-{2}", request.getServiceId(), request.getDataId(), flowExceptionRequest.getExceptionId()+"-10")));
                    saveAutoProcessException(request,flowExceptionRequest.getExceptionId(),afsGreatWallWorkflowBizData.getFlowInstanceId(),exceptionCheckCode);
                }else {
                    if (noticeBiz(request, afsGreatWallWorkflowMappingInfo)) {
                        flowExceptionResponse.setSuccess(true);
                    } else {
                        saveError(request, afsGreatWallWorkflowBizData,false);
                        flowExceptionResponse.setSuccess(false);
                    }
                }
            } else {
                throw new AfsBaseException("通知数据失败");
            }
        } catch (Exception e) {
            saveError(request, afsGreatWallWorkflowBizData,false);
            throw e;
        }
        return JSONObject.toJSONString(flowExceptionResponse);
    }

    private void saveAutoProcessException(GwtRequest request,String exceptionId,String flowInstanceId,String exceptionCheckCode){
        if (afsGreatWallWorkflowNoticeExceptionService.count(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getExceptionCheckCode, exceptionCheckCode)) > 0) {
            log.warn("异常已经记录，异常校验码{}", exceptionCheckCode);
            return;
        }
        AfsGreatWallWorkflowNoticeException afsGreatWallWorkflowNoticeException = new AfsGreatWallWorkflowNoticeException();
        afsGreatWallWorkflowNoticeException.setFlowServiceId(request.getServiceId());
        afsGreatWallWorkflowNoticeException.setBizDataId(request.getDataId());
        afsGreatWallWorkflowNoticeException.setNoticeInfo(exceptionId);
        afsGreatWallWorkflowNoticeException.setNoticeType("auto-auto");
        afsGreatWallWorkflowNoticeException.setFlowInstanceId(flowInstanceId);
        afsGreatWallWorkflowNoticeException.setExceptionCheckCode(exceptionCheckCode);
        afsGreatWallWorkflowNoticeExceptionService.save(afsGreatWallWorkflowNoticeException);
    }
    private void saveError(GwtRequest request, AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData,boolean auto) {
        if (afsGreatWallWorkflowBizData != null) {
            FlowExceptionRequest flowExceptionRequest = JSON.parseObject(request.getBody(), FlowExceptionRequest.class);
           if(auto){
               saveAutoException(request, afsGreatWallWorkflowBizData.getFlowInstanceId(), (genExceptionCheckCode(MessageFormat.format("{0}-{1}-{2}", request.getServiceId(), request.getDataId(), flowExceptionRequest.getExceptionId()))));
           }else {
               saveException(request, afsGreatWallWorkflowBizData.getFlowInstanceId(), (genExceptionCheckCode(MessageFormat.format("{0}-{1}-{2}", request.getServiceId(), request.getDataId(), flowExceptionRequest.getExceptionId()))));
           }
            afsGreatWallWorkflowBizData.setFlowStatus(FlowStatus.ERROR);
            String bizData="{}";
            if(StringUtils.isNotEmpty(afsGreatWallWorkflowBizData.getBizData())){
                bizData = afsGreatWallWorkflowBizData.getBizData();
            }
            JSONObject bizDataJson = JSONObject.parseObject(bizData);
            bizDataJson.put(FLOW_EXCEPTION_DESC_KEY,AfsEnumUtil.desc(request.getObjectCode()));
            afsGreatWallWorkflowBizData.setBizData(bizDataJson.toJSONString());
            afsGreatWallWorkflowBizDataService.updateById(afsGreatWallWorkflowBizData);
        }
    }

    private void saveAutoException(GwtRequest request, String flowInstanceId, String exceptionCheckCode){
        if (afsGreatWallWorkflowNoticeExceptionService.count(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getExceptionCheckCode, exceptionCheckCode)) > 0) {
            log.warn("异常已经记录，异常校验码{}", exceptionCheckCode);
            return;
        }
        AfsGreatWallWorkflowNoticeException afsGreatWallWorkflowNoticeException = new AfsGreatWallWorkflowNoticeException();
        afsGreatWallWorkflowNoticeException.setFlowServiceId(request.getServiceId());
        afsGreatWallWorkflowNoticeException.setBizDataId(request.getDataId());
        afsGreatWallWorkflowNoticeException.setNoticeInfo(JSON.toJSONString(request));
        afsGreatWallWorkflowNoticeException.setNoticeType(processKey());
        afsGreatWallWorkflowNoticeException.setFlowInstanceId(flowInstanceId);
        afsGreatWallWorkflowNoticeException.setExceptionCheckCode(exceptionCheckCode);
        afsGreatWallWorkflowNoticeExceptionService.save(afsGreatWallWorkflowNoticeException);
        afsGreatWallWorkflowNoticeExceptionService.removeById(afsGreatWallWorkflowNoticeException.getId());
    }

    @Override
    protected void saveException(GwtRequest request, String flowInstanceId, String exceptionCheckCode) {
        if (afsGreatWallWorkflowNoticeExceptionService.count(Wrappers.<AfsGreatWallWorkflowNoticeException>lambdaQuery().eq(AfsGreatWallWorkflowNoticeException::getExceptionCheckCode, exceptionCheckCode)) > 0) {
            log.warn("异常已经记录，异常校验码{}", exceptionCheckCode);
            return;
        }
        AfsGreatWallWorkflowNoticeException afsGreatWallWorkflowNoticeException = new AfsGreatWallWorkflowNoticeException();
        afsGreatWallWorkflowNoticeException.setFlowServiceId(request.getServiceId());
        afsGreatWallWorkflowNoticeException.setBizDataId(request.getDataId());
        afsGreatWallWorkflowNoticeException.setNoticeInfo(JSON.toJSONString(request));
        afsGreatWallWorkflowNoticeException.setNoticeType(processKey());
        afsGreatWallWorkflowNoticeException.setFlowInstanceId(flowInstanceId);
        afsGreatWallWorkflowNoticeException.setExceptionCheckCode(exceptionCheckCode);
        afsGreatWallWorkflowNoticeExceptionService.save(afsGreatWallWorkflowNoticeException);
    }

    @Override
    public boolean processError(GwtRequest request) {
        AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo = afsGreatWallWorkflowMappingInfoService.queryMappingByServiceId(request.getServiceId());
        if (afsGreatWallWorkflowMappingInfo != null) {
            try {
                return noticeBiz(request, afsGreatWallWorkflowMappingInfo);
            } catch (Exception e) {
                return false;
            }
        } else {
            return false;
        }
    }
    protected FlowExceptionRequest getFlowExceptionRequest (GwtRequest request){
        return  JSON.parseObject(request.getBody(), FlowExceptionRequest.class);
    }

    protected AfsFlowQueryRequest<FlowExceptionRequest> getRequest(GwtRequest request, AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo){
        AfsFlowQueryRequest<FlowExceptionRequest> afsFlowQueryRequest = new AfsFlowQueryRequest<>();
        FlowExceptionRequest flowExceptionRequest = getFlowExceptionRequest(request);
        afsFlowQueryRequest.setData(flowExceptionRequest);
        afsFlowQueryRequest.setAfsFlowKey(afsGreatWallWorkflowMappingInfo.getAfsFlowKey());
        flowExceptionRequest.setServiceId(request.getServiceId());
        flowExceptionRequest.setBizDataId(request.getDataId());
        flowExceptionRequest.setAfsFlowKey(FlowMappingHelper.getAfsKey(request.getServiceId()));
        return  afsFlowQueryRequest;
    }

    abstract boolean noticeBiz(GwtRequest request,AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo);
}
